#include "ce_vulkan_context.h"
#include "ce_vulkan_struct.h"
#include "ce_vulkan_manager.h"
#include "../math/ce_vec4.h"
#include <algorithm>

CE_VulkanContext::CE_VulkanContext(GLFWwindow *window, VkPhysicalDevice physicalDevice, VkDevice vkdevice, VkSurfaceKHR surface)
{
    this->_window = window;
    this->_physicalDevice = physicalDevice;
    this->_vkdevice = vkdevice;
    this->_surface = surface;
    this->_createSwapChain();
    this->_createImageViews();
    this->_createPass();
    // this->_createFramebuffers();
    this->_createCommandPool();
    this->_createSyncObjects();
    this->_createFirstClearObject();

    // // 1
    // CE_VulkanObject *object1 = new CE_VulkanObject(this, CE_VulkanObjectTypeE::UI);
    // std::vector<Vertex> vertices1 = {
    //     {{0.0f, 0.8f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}},
    //     {{-0.8f, -0.8f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}},
    //     {{0.8f, -0.8f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}},
    // };
    // std::vector<uint32_t> indices1 = {0, 1, 2};
    // object1->setVertexs(vertices1, indices1);
    // object1->setColor(1.0f, 0.0f, 0.0f, 1.0f);

    // // 统一管理shader
    // std::string shaderPath = "resources/effects/default/default";
    // if (this->_shaders.find(shaderPath) == this->_shaders.end())
    // {
    //     this->_shaders[shaderPath] = new CE_VulkanShader(this->_vkdevice, shaderPath);
    // }

    // // 通过shader 和 pass 检索对应的pipeline
    // std::string pipelineKey = std::string("DEFAULT_UI_PASS") + "_" + shaderPath;
    // if (this->_pipelines.find(pipelineKey) == this->_pipelines.end())
    // {
    //     this->_pipelines[pipelineKey] = new CE_VulkanPipeline(this, CE_VulkanObjectTypeE::UI, this->_shaders[shaderPath], this->_pass["DEFAULT_UI_PASS"]);
    // }
    // object1->setRendererPipeline(this->_pipelines[pipelineKey]);
    // this->_uiObjects["text_0"] = object1;

    // 2

    // CE_Vec4 _positions[4];
    // _positions[0] = CE_Vec4(-1.0f, 1.0f, 0.0f, 0.0f);
    // _positions[1] = CE_Vec4(-1.0f, -1.0f, 0.0f, 0.0f);
    // _positions[2] = CE_Vec4(1.0f, -1.0f, 0.0f, 0.0f);
    // _positions[3] = CE_Vec4(1.0f, 1.0f, 0.0f, 0.0f);

    // int _indices[6];
    // _indices[0] = 0;
    // _indices[1] = 1;
    // _indices[2] = 2;
    // _indices[3] = 0;
    // _indices[4] = 2;
    // _indices[5] = 3;

    // this->addUIObject("text_0");
    // this->updateUIObjectShader("text_0", "resources/effects/default/default");

    // std::vector<float> positions;
    // for (int i = 0; i < 4; i++)
    // {
    //     positions.push_back(_positions[i].getX());
    //     positions.push_back(_positions[i].getY());
    //     positions.push_back(_positions[i].getZ());
    //     positions.push_back(_positions[i].getW());
    // }
    // std::vector<int> indices={0,1,2};

    // this->updateUIObjectVertexs("text_0",positions,indices);
    // this->_uiObjects["text_0"]->setColor(0.0f, 1.0f, 0.0f, 0.1f);
}
VkDevice CE_VulkanContext::getVKDevice()
{
    return this->_vkdevice;
}
/**
 * @brief 创建交换链
 *
 */
void CE_VulkanContext::_createSwapChain()
{
    std::cout << "create swap chain start..." << std::endl;
    SwapChainSupportDetails swapChainSupport = CE_VulkanManager::getInstance()->querySwapChainSupport(this->_physicalDevice);

    VkSurfaceFormatKHR surfaceFormat = this->_chooseSwapSurfaceFormat(swapChainSupport.formats);
    VkPresentModeKHR presentMode = this->_chooseSwapPresentMode(swapChainSupport.presentModes);
    VkExtent2D extent = this->_chooseSwapExtent(swapChainSupport.capabilities);

    uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
    if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
    {
        imageCount = swapChainSupport.capabilities.maxImageCount;
    }

    VkSwapchainCreateInfoKHR createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.surface = this->_surface;
    createInfo.minImageCount = imageCount;
    createInfo.imageFormat = surfaceFormat.format;
    createInfo.imageColorSpace = surfaceFormat.colorSpace;
    createInfo.imageExtent = extent;
    createInfo.imageArrayLayers = 1;                             // 用于指定每个图像所包含的层次。除了VR场景外，一般都是1.
    createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // 指定我们在图像上的操作，此处我们将图像作为颜色来使用
    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
    /**
     * VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
     * VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR
     * VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
     */

    QueueFamilyIndices indices = CE_VulkanManager::getInstance()->findQueueFamilies(this->_physicalDevice);
    uint32_t queueFamilyIndices[] = {(uint32_t)indices.graphicsFamily, (uint32_t)indices.presentFamily};

    if (indices.graphicsFamily != indices.presentFamily)
    {
        createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        createInfo.queueFamilyIndexCount = 2;
        createInfo.pQueueFamilyIndices = queueFamilyIndices;
    }
    else
    {
        createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
        createInfo.queueFamilyIndexCount = 0;     // Optional
        createInfo.pQueueFamilyIndices = nullptr; // Optional
    }

    createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
    // createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // 忽略alpha通道
    createInfo.presentMode = presentMode;
    createInfo.clipped = VK_TRUE;

    createInfo.oldSwapchain = VK_NULL_HANDLE;

    if (vkCreateSwapchainKHR(this->_vkdevice, &createInfo, nullptr, &this->_swapChain) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to create swap chain!");
    }

    std::cout << "create swap chain success..." << std::endl;

    // 用vkGetSwapchainImagesKHR查询最终的图像数量
    vkGetSwapchainImagesKHR(this->_vkdevice, this->_swapChain, &imageCount, nullptr);
    // 创建交换链图像数组
    this->_swapChainImages.resize(imageCount);
    vkGetSwapchainImagesKHR(this->_vkdevice, this->_swapChain, &imageCount, this->_swapChainImages.data());
    // 同时还需要将这个格式和分辨率保存下来。
    this->_swapChainImageFormat = surfaceFormat.format;
    this->_swapChainExtent = extent;
}
VkExtent2D CE_VulkanContext::getSwapChainExtent()
{
    return this->_swapChainExtent;
}
std::vector<VkImage> CE_VulkanContext::getSwapChainImages()
{
    return this->_swapChainImages;
}

// https://www.iogl.cn/tutorial/swapchain
VkSurfaceFormatKHR CE_VulkanContext::_chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats)
{
    // 优先选择 B8G8R8A8_UNORM + SRGB
    for (const auto &availableFormat : availableFormats)
    {
        if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
        {
            return availableFormat;
        }
    }
    // 次优选择：任何带 Alpha 的格式
    for (const auto &format : availableFormats)
    {
        if (format.format == VK_FORMAT_B8G8R8A8_UNORM ||
            format.format == VK_FORMAT_R8G8B8A8_UNORM)
        {
            return format;
        }
    }

    return availableFormats[0];
}
// https://www.iogl.cn/tutorial/swapchain
VkPresentModeKHR CE_VulkanContext::_chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
{
    for (const auto &availablePresentMode : availablePresentModes)
    {
        if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
        {
            return availablePresentMode;
        }
    }

    return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D CE_VulkanContext::_chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
{
    if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
    {
        return capabilities.currentExtent;
    }
    else
    {
        int width, height;
        glfwGetFramebufferSize(this->_window, &width, &height);

        VkExtent2D actualExtent = {
            static_cast<uint32_t>(width),
            static_cast<uint32_t>(height)};

        actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
        actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);

        return actualExtent;
    }
}
/**
 * @brief 创建交换链图像视图
 *
 */
void CE_VulkanContext::_createImageViews()
{
    std::cout << "create ImageViews start..." << std::endl;
    this->_swapChainImageViews.resize(this->_swapChainImages.size());
    for (size_t i = 0; i < this->_swapChainImages.size(); i++)
    {
        VkImageViewCreateInfo createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        createInfo.image = this->_swapChainImages[i];
        createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        createInfo.format = this->_swapChainImageFormat;
        createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        createInfo.subresourceRange.baseMipLevel = 0;
        createInfo.subresourceRange.levelCount = 1;
        createInfo.subresourceRange.baseArrayLayer = 0;
        createInfo.subresourceRange.layerCount = 1;
        if (vkCreateImageView(this->_vkdevice, &createInfo, nullptr, &this->_swapChainImageViews[i]) != VK_SUCCESS)
        {
            throw std::runtime_error("failed to create image views!");
        }
    }
    std::cout << "create ImageViews success..." << std::endl;
}
std::vector<VkImageView> CE_VulkanContext::getSwapChainImageViews()
{
    return this->_swapChainImageViews;
}

/**
 * @brief 创建渲染通道
 * 渲染通道是一个VkRenderPass对象，它描述了渲染的目标和渲染的过程。
 * 渲染通道的目标是一个或多个VkFramebuffer对象，每个VkFramebuffer对象都包含了一个或多个VkImageView对象。
 * 渲染通道的过程是一个或多个VkSubpass对象，每个VkSubpass对象都包含了一个或多个VkAttachment对象。
 * 渲染通道的目标和过程都是在渲染命令中指定的。
 */
void CE_VulkanContext::_createPass()
{

    CE_VulkanPass *pass = new CE_VulkanPass("DEFAULT_PASS", CE_VulkanObjectTypeE::DEFAULT, this->_vkdevice, this->_swapChainImageFormat);
    this->_pass["DEFAULT_PASS"] = pass;

    CE_VulkanPass *uiPass = new CE_VulkanPass("DEFAULT_UI_PASS", CE_VulkanObjectTypeE::UI, this->_vkdevice, this->_swapChainImageFormat);
    this->_pass["DEFAULT_UI_PASS"] = uiPass;
}
/*
 * @brief 创建命令池
 */
void CE_VulkanContext::_createCommandPool()
{

    std::cout << "create command pool start..." << std::endl;
    QueueFamilyIndices queueFamilyIndices = CE_VulkanManager::getInstance()->findQueueFamilies(this->_physicalDevice);

    VkCommandPoolCreateInfo poolInfo{};
    poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    // 每个命令池只能分配在单一类型队列上提交的Command Buffer。我们将记录绘图命令，这就是我们选择图形队列系列的原因。
    poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;

    // 创建Command Pool
    if (vkCreateCommandPool(this->_vkdevice, &poolInfo, nullptr, &this->_commandPool) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to create command pool!");
    }
    std::cout << "create command pool success..." << std::endl;
}

VkCommandPool CE_VulkanContext::getCommandPool()
{
    return this->_commandPool;
}

void CE_VulkanContext::_createSyncObjects()
{
    std::cout << "create sync objects start..." << std::endl;
    size_t imageCount = this->_swapChainImages.size(); // 使用交换链图像数量
    this->_imageAvailableSemaphores.resize(imageCount);
    this->_renderFinishedSemaphores.resize(imageCount);
    this->_inFlightFences.resize(imageCount);
    this->_imagesInFlight.resize(imageCount, VK_NULL_HANDLE);

    VkSemaphoreCreateInfo semaphoreInfo{};
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

    VkFenceCreateInfo fenceInfo{};
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;

    for (size_t i = 0; i < imageCount; i++)
    {
        if (vkCreateSemaphore(this->_vkdevice, &semaphoreInfo, nullptr, &this->_imageAvailableSemaphores[i]) != VK_SUCCESS ||
            vkCreateSemaphore(this->_vkdevice, &semaphoreInfo, nullptr, &this->_renderFinishedSemaphores[i]) != VK_SUCCESS ||
            vkCreateFence(this->_vkdevice, &fenceInfo, nullptr, &this->_inFlightFences[i]) != VK_SUCCESS)
        {
            throw std::runtime_error("Failed to create synchronization objects for a frame!");
        }
    }
    std::cout << "create sync objects success..." << std::endl;
}
void CE_VulkanContext::_createFirstClearObject()
{

    /**
     * -1,1     0,1      1,1
     *
     * 0,-1     0,0      0,1
     *
     * -1,-1    0,-1     1,-1
     */

    this->_firstClearObject = new CE_VulkanObject(this, CE_VulkanObjectTypeE::DEFAULT);
    std::vector<Vertex> vertices = {
        {{-1.0f, 1.0f, 0.0f, 0.0f},
         {1.0f, 0.0f, 0.0f, 1.0f}},

        {{-1.0f, -1.0f, 0.0f, 0.0f},
         {0.0f, 1.0f, 0.0f, 1.0f}},

        {{1.0f, -1.0f, 0.0f, 0.0f},
         {0.0f, 0.0f, 1.0f, 1.0f}},

        {{1.0f, 1.0f, 1.0f, 0.0f},
         {0.0f, 0.0f, 1.0f, 1.0f}},
    };
    std::vector<uint32_t> indices = {0, 1, 2, 0, 2, 3};
    this->_firstClearObject->setVertexs(vertices, indices);
    this->_firstClearObject->setClear(true);
    this->_firstClearObject->setColor(0.0f, 0.0f, 0.0f, 0.0f);

    // 统一管理shader
    std::string shaderPath = "resources/effects/default/default";
    if (this->_shaders.find(shaderPath) == this->_shaders.end())
    {
        this->_shaders[shaderPath] = new CE_VulkanShader(this->_vkdevice, shaderPath);
    }

    // 通过shader 和 pass 检索对应的pipeline
    std::string pipelineKey = std::string("DEFAULT_PASS") + "_" + shaderPath;
    if (this->_pipelines.find(pipelineKey) == this->_pipelines.end())
    {
        this->_pipelines[pipelineKey] = new CE_VulkanPipeline(this, CE_VulkanObjectTypeE::UI, this->_shaders[shaderPath], this->_pass["DEFAULT_PASS"]);
    }
    this->_firstClearObject->setRendererPipeline(this->_pipelines[pipelineKey]);
}
/**
 * @brief 添加UI对象
 *
 * @param id
 */
void CE_VulkanContext::addUIObject(std::string id)
{
    // std::cout << "add ui object " << id << std::endl;
    CE_VulkanObject *object = new CE_VulkanObject(this, CE_VulkanObjectTypeE::UI);
    this->_uiObjects[id] = object;
    _insertionOrder.push_back(id);
}
void CE_VulkanContext::updateUIObjectShader(std::string id, std::string shaderPath)
{
    // std::cout << "update ui object shader " << id << " " << shaderPath << std::endl;
    // 统一管理shader
    if (this->_shaders.find(shaderPath) == this->_shaders.end())
    {
        this->_shaders[shaderPath] = new CE_VulkanShader(this->_vkdevice, shaderPath);
    }
    // 通过shader 和 pass 检索对应的pipeline
    std::string pipelineKey = std::string("DEFAULT_UI_PASS") + "_" + shaderPath;
    if (this->_pipelines.find(pipelineKey) == this->_pipelines.end())
    {
        this->_pipelines[pipelineKey] = new CE_VulkanPipeline(this, CE_VulkanObjectTypeE::UI, this->_shaders[shaderPath], this->_pass["DEFAULT_UI_PASS"]);
    }
    this->_uiObjects[id]->setRendererPipeline(this->_pipelines[pipelineKey]);
}
void CE_VulkanContext::updateUIObjectVertexs(std::string id, std::vector<float> positions, std::vector<int> indices)
{
    // std::cout << "update ui object vertexs " << id << std::endl;
    // 将positions转换为Vertex
    std::vector<Vertex> _vertices;
    for (size_t i = 0; i < positions.size() / 4; i++)
    {
        _vertices.push_back(
            {{positions[i * 4], positions[i * 4 + 1], positions[i * 4 + 2], positions[i * 4 + 3]}, // 顶点
             {1.0f, 0.0f, 0.0f, 1.0f}});
    }
    // 将indices转换为uint32_t
    std::vector<uint32_t> _indices;
    for (size_t i = 0; i < indices.size(); i++)
    {
        _indices.push_back(indices[i]);
    }
    this->_uiObjects[id]->setVertexs(_vertices, _indices);
}
void CE_VulkanContext::updateUIObjectColor(std::string id, float r, float g, float b, float a)
{
    // std::cout << "update ui object color " << id << " " << r << " " << g << " " << b << " " << a << std::endl;
    this->_uiObjects[id]->setColor(r, g, b, a);
}

void CE_VulkanContext::drawFrame()
{

    vkWaitForFences(this->_vkdevice, 1, &this->_inFlightFences[this->_currentFrame], VK_TRUE, UINT64_MAX);
    uint32_t imageIndex = this->_acquireNextImage();

    std::vector<VkCommandBuffer> commandBuffersToSubmit;

    this->_firstClearObject->updateRender();
    commandBuffersToSubmit.push_back(this->_firstClearObject->getCommandBuffer(imageIndex));

    // for (auto &[name, object] : this->_uiObjects)
    // {
    //     if (object)
    //     { // 安全检查
    //         object->updateRender();

    //         VkCommandBuffer cmd = object->getCommandBuffer(imageIndex);
    //         // // 2. 可选：更新物体的Uniform缓冲区
    //         // // object->updateUniformBuffer(cameraView, cameraProj);
    //         // // 3. 收集命令缓冲
    //         commandBuffersToSubmit.push_back(cmd);
    //     }
    // }

    for (const auto &name : this->_insertionOrder)
    {
       if (this->_uiObjects[name])
        {
            this->_uiObjects[name]->updateRender();

            VkCommandBuffer cmd = this->_uiObjects[name]->getCommandBuffer(imageIndex);
            // // 2. 可选：更新物体的Uniform缓冲区
            // // object->updateUniformBuffer(cameraView, cameraProj);
            // // 3. 收集命令缓冲
            commandBuffersToSubmit.push_back(cmd);
        }
    }

    this->_submitCommands(imageIndex, commandBuffersToSubmit);
    this->_presentFrame(imageIndex);
    this->_currentFrame = (this->_currentFrame + 1) % this->_swapChainImages.size();
}

uint32_t CE_VulkanContext::_acquireNextImage()
{
    uint32_t imageIndex;
    // 参数1：逻辑设备对象
    // 参数2：获取图像的交换链
    // 参数3：获取图像的超时时间
    // 参数4：指定信号量，用于同步
    // 参数5：默认值
    // 参数6：输出可用的交换链图像的索引
    vkAcquireNextImageKHR(this->_vkdevice, this->_swapChain, UINT64_MAX, this->_imageAvailableSemaphores[this->_currentFrame], VK_NULL_HANDLE, &imageIndex);

    // 等待该图像关联的fence（避免资源冲突）
    if (this->_imagesInFlight[imageIndex] != VK_NULL_HANDLE)
    {
        vkWaitForFences(this->_vkdevice, 1, &this->_imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
    }
    this->_imagesInFlight[imageIndex] = this->_inFlightFences[this->_currentFrame];

    return imageIndex;
}
void CE_VulkanContext::_submitCommands(uint32_t imageIndex, const std::vector<VkCommandBuffer> &commandBuffers)
{
    // 等待信号量配置（图像可用时触发）
    VkSemaphore waitSemaphores[] = {this->_imageAvailableSemaphores[this->_currentFrame]};
    VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};

    // 完成渲染后触发的信号量
    VkSemaphore signalSemaphores[] = {this->_renderFinishedSemaphores[this->_currentFrame]};

    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = waitStages;
    submitInfo.commandBufferCount = static_cast<uint32_t>(commandBuffers.size());
    submitInfo.pCommandBuffers = commandBuffers.data();
    submitInfo.signalSemaphoreCount = 1;

    submitInfo.pSignalSemaphores = signalSemaphores;
    vkResetFences(this->_vkdevice, 1, &this->_inFlightFences[this->_currentFrame]);

    if (vkQueueSubmit(CE_VulkanManager::getInstance()->getGraphicsQueue(), 1, &submitInfo, this->_inFlightFences[this->_currentFrame]) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to submit draw command buffer!");
    }
}
void CE_VulkanContext::_presentFrame(uint32_t imageIndex)
{
    VkSemaphore signalSemaphores[] = {this->_renderFinishedSemaphores[this->_currentFrame]};
    VkSwapchainKHR swapChains[] = {this->_swapChain};
    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.waitSemaphoreCount = 1;
    presentInfo.pWaitSemaphores = signalSemaphores;
    presentInfo.swapchainCount = 1;
    presentInfo.pSwapchains = swapChains;
    presentInfo.pImageIndices = &imageIndex;
    vkQueuePresentKHR(CE_VulkanManager::getInstance()->getPresentQueue(), &presentInfo);
}